package com.douziit.meilianoa.base.redis;

import com.douziit.meilianoa.base.enums.ResponseCode;
import com.douziit.meilianoa.base.exception.TipException;
import com.douziit.meilianoa.base.utils.TokenUtil;
import com.douziit.meilianoa.base.utils.config.JsonMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

/**
 * 用户Token操作
 *
 * @author MrShun
 * @version 1.0
 */
@Service
public class AppUserTokenService<T> {

    private final static Logger LOG = LoggerFactory.getLogger(AppUserTokenService.class);

    @Autowired
    private RedisService redisService;

    private final static String CURRENT_TIME = "currentTime";

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 设置多长时间无操作则重新登录, 3天
     */
    @Value("${token.expireTime:259200000}")
    private Long expireTime = 0L;
    /**
     * PC端设置多长时间无操作则重新登录, 1小时
     */
    private Long pcExpireTime = 3600000L;

    /**
     * 创建userTokenStr
     *
     * @param userToken
     * @return
     */
    public String generate(UserTokenBean userToken, T userInfo) {


        String userTokenStr = TokenUtil.generator(userToken.getMD5Str());
        String userTokenStrKey = TokenUtil.getKey(RedisConstant.APP_USER_TOKEN_REDIS_PREFIX, userTokenStr);
        JsonMap userInfoExt = new JsonMap(userInfo);
        userInfoExt.put(CURRENT_TIME, System.currentTimeMillis());

        //此处单点登录构造单用户token管理  获取用户上一个token
        String mangerKey = TokenUtil.userTokenMangerKey(userToken.getUid());
        ValueOperations<String, String> tokenmanager = redisTemplate.opsForValue();

        String appuserToken = tokenmanager.get(mangerKey);
        if (appuserToken!=null&&!"".equals(appuserToken)) {
            Boolean exist = redisTemplate.hasKey(appuserToken);
            if (exist) {
                redisTemplate.delete(appuserToken);
            }

        }
        redisService.set(userTokenStrKey, userInfoExt);
        redisService.set(RedisConstant.APP_USER_ID_REDIS_PREFIX + userToken.getUid(), userTokenStr);
        //添加用户tonken管理记录
        tokenmanager.set(mangerKey,userTokenStrKey);
        return userTokenStr;
    }

    /**
     * 检查userTokenStr有效性
     *
     * @param userTokenStr
     * @return
     * @throws Exception
     */
    public JsonMap checkValidity(String userTokenStr) {
        String userTokenKey = TokenUtil.getKey(RedisConstant.APP_USER_TOKEN_REDIS_PREFIX, userTokenStr);
        if (!redisService.exists(userTokenKey)) {
            throw new TipException(ResponseCode.INVALID_TOKEN_INFO);
        }
        JsonMap userInfoExt = redisService.get(userTokenKey);
        Long lastTime = userInfoExt.getLong(CURRENT_TIME);
        long currentTime = System.currentTimeMillis();
        if (expireTime != 0 && currentTime - lastTime > expireTime) {
            throw new TipException(ResponseCode.EXPIRATION_TOKEN_INFO);
        }
        userInfoExt.put(CURRENT_TIME, System.currentTimeMillis());
        //删除原有的Token
        deleteUserToken(userTokenKey);
        redisService.set(userTokenKey, userInfoExt);
        return userInfoExt;
    }

    /**
     * 检查PC端userTokenStr有效性（1小时）
     *
     * @param userTokenStr
     * @return
     * @throws Exception
     */
    public JsonMap checkPcValidity(String userTokenStr) {
        String userTokenKey = TokenUtil.getKey(RedisConstant.APP_USER_TOKEN_REDIS_PREFIX, userTokenStr);
        if (!redisService.exists(userTokenKey)) {
            throw new TipException(ResponseCode.INVALID_TOKEN_INFO);
        }
        JsonMap userInfoExt = redisService.get(userTokenKey);
        Long lastTime = userInfoExt.getLong(CURRENT_TIME);
        long currentTime = System.currentTimeMillis();
        if (pcExpireTime != 0 && currentTime - lastTime > pcExpireTime) {
            throw new TipException(ResponseCode.EXPIRATION_TOKEN_INFO);
        }
        userInfoExt.put(CURRENT_TIME, System.currentTimeMillis());
        //删除原有的Token
        deleteUserToken(userTokenKey);
        redisService.set(userTokenKey, userInfoExt);
        return userInfoExt;
    }
    /**
     * 删除用户userToken
     *
     * @param userTokenStr
     * @throws Exception
     */
    public void deleteUserToken(String userTokenStr) {
        String userTokenKey = TokenUtil.getKey(RedisConstant.APP_USER_TOKEN_REDIS_PREFIX, userTokenStr);
        redisService.remove(userTokenKey);
    }

    /**
     * 查询用户信息
     *
     * @param userTokenStr
     * @throws Exception
     */
    public JsonMap findUserInfo(String userTokenStr) {
        String userTokenKey = TokenUtil.getKey(RedisConstant.APP_USER_TOKEN_REDIS_PREFIX, userTokenStr);
        return redisService.get(userTokenKey);
    }

    /**
     * 查询用户Token信息
     *
     * @param userId 用户ID
     * @throws Exception
     */
    public String findUserToken(Integer userId) {
        return redisService.get(RedisConstant.APP_USER_ID_REDIS_PREFIX + userId);
    }


    /**
     * 根据用户ID删除当前用户所有token
     * @param uid
     */
    public void deleteUserTokenByUid(Integer uid){
        String userToken = findUserToken(uid);
        deleteUserToken(userToken);
    }
}
